package com.mallcloud.mall.app.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mallcloud.mall.app.mapper.AppProcedureMapper;
import com.mallcloud.mall.app.service.AppPointsCouponService;
import com.mallcloud.mall.common.core.constant.enums.RLockEnum;
import com.mallcloud.mall.common.core.constant.enums.mall.PointsCouponEnum;
import com.mallcloud.mall.common.core.exception.FailException;
import com.mallcloud.mall.common.data.resolver.TenantResolver;
import com.mallcloud.mall.mall.api.entity.dto.*;
import com.mallcloud.mall.mall.api.entity.vo.MallPointsCouponVO;
import com.mallcloud.mall.mall.service.MallPointsCouponService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 卡券管理
 */
@Slf4j
@Service
@AllArgsConstructor
public class AppCouponServiceImpl implements AppPointsCouponService {

	private final Redisson redisson;
	private final AppProcedureMapper procedureMapper;
	private final MallPointsCouponService mallPointsCouponService;

    @Override
    public IPage<MallPointsCouponVO> payCouponPage(Page<MallPointsCouponVO> page) {
        log.info("查询{}...", PointsCouponEnum.PurposeEnum.PAY.getDescription());
		MallPointsCouponVO dto = new MallPointsCouponVO();
		dto.setPurpose(PointsCouponEnum.PurposeEnum.PAY.getCode());
		Page<MallPointsCouponVO> pageResult = mallPointsCouponService.page(page, dto);

		pageResult.getRecords().forEach(o -> o.setPurposeName(PointsCouponEnum.PurposeEnum.getDecs(o.getPurpose())));
		return pageResult;
	}

    @Override
    public IPage<MallPointsCouponVO> freeCouponPage(Page<MallPointsCouponVO> page) {
        log.info("查询{}...", PointsCouponEnum.PurposeEnum.FREE.getDescription());
		MallPointsCouponVO dto = new MallPointsCouponVO();
		dto.setPurpose(PointsCouponEnum.PurposeEnum.FREE.getCode());
		Page<MallPointsCouponVO> pageResult = mallPointsCouponService.page(page, dto);

		pageResult.getRecords().forEach(o -> o.setPurposeName(PointsCouponEnum.PurposeEnum.getDecs(o.getPurpose())));
		return pageResult;
    }

    @Override
    public IPage<MallPointsCouponVO> redeemCouponPage(Page<MallPointsCouponVO> page) {
        log.info("查询{}...", PointsCouponEnum.PurposeEnum.REDEEM.getDescription());
		MallPointsCouponVO dto = new MallPointsCouponVO();
		dto.setPurpose(PointsCouponEnum.PurposeEnum.REDEEM.getCode());
		Page<MallPointsCouponVO> pageResult = mallPointsCouponService.page(page, dto);

		pageResult.getRecords().forEach(o -> o.setPurposeName(PointsCouponEnum.PurposeEnum.getDecs(o.getPurpose())));
		return pageResult;
    }

	@Override
	public MallPointsCouponVO getInfo(MallPointsCouponVO dto) {
		return mallPointsCouponService.getInfo(dto);
	}

    @SneakyThrows
	@Override
    public void proRedeemCoupon(ProRedeemCoupon dto) {
		if(StrUtil.isBlank(dto.getStoreNo())){
			dto.setStoreNo(TenantResolver.getById().getCode());
		}
        procedureMapper.redeemCoupon(dto);
        if (!dto.isSuccess()) {
			log.error("失败");
			throw new FailException(dto.getMessage());
        }
    }

	@SneakyThrows
    @Override
    public void proGetCoupon(ProGetCoupon dto) {
		if(StrUtil.isBlank(dto.getStoreNo())){
			dto.setStoreNo(TenantResolver.getById().getCode());
		}
        procedureMapper.getCoupon(dto);
		if (!dto.isSuccess()) {
			log.error("失败");
			throw new FailException(dto.getMessage());
        }
    }

	@SneakyThrows
    @Override
    public List<ProPayCouponInfo> proPayCoupon(ProPayCoupon dto) {
		if(StrUtil.isBlank(dto.getStoreNo())){
			dto.setStoreNo(TenantResolver.getById().getCode());
		}
        procedureMapper.payCoupon(dto);
        if (!dto.isSuccess()) {
			log.error("失败");
			throw new FailException(dto.getMessage());
        }
        return dto.getBillNo();
    }

	@SneakyThrows
    @Override
    public String proCheckPayCoupon(ProPayCoupon dto) {
		String payNo = String.valueOf(IdUtil.getSnowflake().nextId());
		if(StrUtil.isBlank(dto.getPayNo())){
    		dto.setPayNo(payNo);
		}
		if(StrUtil.isBlank(dto.getStoreNo())){
			dto.setStoreNo(TenantResolver.getById().getCode());
		}

        procedureMapper.payCouponCheck(dto);
        if (!dto.isSuccess()) {
			log.error("失败");
			throw new FailException(dto.getMessage());
        }
        return payNo;
    }

	@SneakyThrows
	@Override
    public void proPayRollBackCoupon(ProPayRollBackCoupon dto) {
        procedureMapper.payRollBackCoupon(dto);
		if (!dto.isSuccess()) {
			log.error("失败");
			throw new FailException(dto.getMessage());
        }
    }

	@SneakyThrows
    @Override
    public void proGivenCoupon(ProGivenCoupon dto) {
		log.info("券-转赠请求请求锁");
		RLock lock = redisson.getLock(RLockEnum.COUPON_GIVEN.getKey(dto.getGivenCouponNumber()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.givenCoupon(dto);
			if (!dto.isSuccess()) {
				log.error("失败");
				throw new FailException(dto.getMessage());
			}
		}
		finally {
			lock.unlock();
		}
    }
}
